#include <math.h>

#include "OTSU.h"

uint8 Get_Threshold(uint8 *image, uint16 width, uint16 height)
{
	const int GrayScale = 256;						// 灰度级别
	int pixel_count[GrayScale] = {0};				// 每种灰度的像素数
	float pixel_pro[GrayScale] = {0};				// 每种灰度的归一化所占比例
	int pixel_sum = (width / 2) * (height / 2) / 2; // 像素总和
	uint8 threshold = 0;							// 阈值
	uint8 threshold_temp = 0;						// 阈值临时计算量
	uint8 *data = image;							// 定义一个指向传进来这个image数组的指针变量data
	unsigned long long gray_sum = 0;							// 整幅灰度图像的灰度值总和
	/*************************统计每个灰度值(0-255)在整幅图像中出现的次数与比例*************************/
	for (int i = 0; i < height; i += 2)	   // 隔行遍历图像
		for (int j = 0; j < width; j += 2) // 隔列遍历图像
		{
			pixel_count[(int)data[i * width + j]]++; // 将当前的像素点的像素值（灰度值）作为计数数组的下标。
			gray_sum += (int)data[i * width + j];	 // 计算整幅灰度图像的灰度值总和。
		}
	for (int i = 0; i < GrayScale; i++)
		pixel_pro[i] = (float)pixel_count[i] / pixel_sum;

	/****************遍历整幅图像的灰度值（0-255）,计算阈值****************/

	float w0 = 0; // 像素小于阈值的概率
	float w1 = 0; // 像素大于阈值的概率
	float u0_temp = 0;
	float u1_temp = 0;
	float u0 = 0; // 小于阈值的平均灰度
	float u1 = 0; // 大于阈值的平均灰度
	float u = 0;  // 全局平均灰度
	float delta_temp = 0;
	float delta_max = 0; // 类间方差最大值
	for (threshold_temp = 0; threshold_temp < GrayScale; threshold_temp++)
	{
		w0 += pixel_pro[threshold_temp]; // 求出背景部分每个灰度值的像素点所占的比例之和，即背景部分的比例。
		u0_temp += threshold_temp * pixel_pro[threshold_temp];

		w1 = 1 - w0;
		u1_temp = gray_sum / pixel_sum - u0_temp;

		u0 = u0_temp / w0;	   // 背景平均灰度
		u1 = u1_temp / w1;	   // 前景平均灰度
		u = u0_temp + u1_temp; // 全局平均灰度
		delta_temp = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);
		if (delta_temp > delta_max)
		{
			delta_max = delta_temp;
			threshold = threshold_temp;
		}
		if (delta_temp < delta_max)
			break;
	}
	// // 三岔降低阈值
	// if (Threshold_Fork_Flag == 1)
	// {
	// 	if (threshold - 28 > 0)
	// 		return threshold - 28;
	// 	else
	// 		return 0;
	// }
	return threshold;
}

void All_IMAGE_OTSU(uint8 imageInput[RESULT_HEIGHT][RESULT_WIDTH], uint8 imageOutput[RESULT_HEIGHT][RESULT_WIDTH],
					uint8 Height, uint8 Width, uint8 OTSU_Threshold)
{
	for (int Ysite = 0; Ysite < Height; Ysite++)
		for (int Xsite = 0; Xsite < Width; Xsite++)
		{
			if (imageInput[Ysite][Xsite] > OTSU_Threshold)
				imageOutput[Ysite][Xsite] = 255;
			else
				imageOutput[Ysite][Xsite] = 0;
		}
}
